package com.ctshk.rpc.insurance.service.impl;

import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.ctshk.common.dto.Result;
import com.ctshk.common.enums.SystemError;
import com.ctshk.common.utils.EntityUtil;
import com.ctshk.rpc.insurance.dto.OfferDTO;
import com.ctshk.rpc.insurance.dto.UnitPriceDTO;
import com.ctshk.rpc.insurance.dto.UserInfoDTO;
import com.ctshk.rpc.insurance.entity.Insurance;
import com.ctshk.rpc.insurance.entity.InsuranceCost;
import com.ctshk.rpc.insurance.mapper.InsuranceCostMapper;
import com.ctshk.rpc.insurance.mapper.InsuranceMapper;
import com.ctshk.rpc.insurance.req.tp.*;
import com.ctshk.rpc.insurance.service.IInsuranceCostService;
import com.ctshk.rpc.insurance.service.IInsuranceService;
import com.google.common.collect.Lists;
import org.apache.dubbo.config.annotation.DubboService;
import org.springframework.beans.factory.annotation.Autowired;

import java.math.BigDecimal;
import java.time.LocalDate;
import java.time.format.DateTimeFormatter;
import java.util.List;
import java.util.Map;
import java.util.Objects;
import java.util.Optional;
import java.util.stream.Collectors;

/**
 * <p>
 * 保险价格成本 服务实现类
 * </p>
 *
 * @author wangcy
 * @since 2021-01-26
 */
@DubboService
public class InsuranceCostServiceImpl extends ServiceImpl<InsuranceCostMapper, InsuranceCost> implements IInsuranceCostService {

    @Autowired
    private IInsuranceService insuranceService;

    @Autowired
    private InsuranceMapper insuranceMapper;

    @Override
    public Result queryPrice(List<PriceReq> priceReq) {
        List<BigDecimal> price = priceReq.stream().map(reqInfo -> {
            Insurance insurance = insuranceMapper.selectById(reqInfo.getId());
            OfferReq offerReq = new OfferReq();
            Offer offer = new Offer();
            offer.setRiskCode(insurance.getApiCode());
            offer.setRationType(insurance.getRationType());
            offer.setStarDate(reqInfo.getStartDate());
            offer.setEndDate(reqInfo.getEndDate());
            offer.setPersonCount(reqInfo.getPersonCount());
            offer.setChildCount(reqInfo.getChildCount());
            offerReq.setData(offer);
            try {
                OfferDTO offerDTO = insuranceService.acciQuotation(offerReq);
                return offerDTO.getPremium();
            } catch (Exception e) {
                log.error("第三方报价查询失败:" + e.getMessage());
                return null;
            }
        }).collect(Collectors.toList());
        if (price.stream().filter(Objects::nonNull).count() != priceReq.size()) {
            return Result.failed(SystemError.SYS_437);
        }
        return Result.success(price.stream().reduce(BigDecimal::add).orElse(new BigDecimal(0)));
    }


    @Override
    public Result queryUnitPrice(UnitPriceReq unitPriceReq) {
        List<Long> ids = unitPriceReq.getIds();
        List<Insurance> insurances = insuranceMapper.selectBatchIds(ids);
        List<InsuranceUser> insuranceUsers = unitPriceReq.getInsuranceUsers();

        Map<String, List<Long>> userIdMap = insuranceUsers
                .stream()
                .collect(Collectors.toMap(InsuranceUser::getUserId,
                        user -> {
                            DateTimeFormatter dateTimeFormatter = DateTimeFormatter.ofPattern("yyyy-MM-dd");
                            LocalDate parse = LocalDate.parse(user.getBirthday(), dateTimeFormatter);
                            LocalDate now = LocalDate.now();
                            int age = now.getYear() - parse.getYear();
                            int monthCompare = now.getMonth().compareTo(parse.getMonth());
                            int dayOfMonth = now.getDayOfMonth() - parse.getDayOfMonth();
                            if (monthCompare < 0) {
                                --age;
                            }
                            if (monthCompare == 0 && dayOfMonth < 0) {
                                --age;
                            }
                            return age;
                        }))
                .entrySet()
                .stream()
                .collect(Collectors.groupingBy(entry -> {
                            if (entry.getValue() >= 18) {
                                return "personIdList";
                            } else {
                                return "childrenIdList";
                            }
                        },
                        Collectors.collectingAndThen(Collectors.toList(), list -> list.stream().map(Map.Entry::getKey).collect(Collectors.toList()))));

        UserInfoDTO userInfoDTO = new UserInfoDTO();
        userInfoDTO.setPersonUserIds(userIdMap.get("personIdList"));
        userInfoDTO.setChildrenUserIds(userIdMap.get("childrenIdList"));
        userInfoDTO.setPersonCount(userIdMap.get("personIdList") == null ? 0 : userIdMap.get("personIdList").size());
        userInfoDTO.setChildrenCount(userIdMap.get("childrenIdList") == null ? 0 : userIdMap.get("childrenIdList").size());

        List<UnitPriceDTO> collect = insurances.stream().map(item -> {
            OfferReq offerReq = new OfferReq();
            Offer offer = new Offer();
            offer.setRiskCode(item.getApiCode());
            offer.setRationType(item.getRationType());
            offer.setStarDate(unitPriceReq.getStartDate());
            offer.setEndDate(unitPriceReq.getEndDate());
            offer.setPersonCount(1L);
            offer.setChildCount(0L);
            offerReq.setData(offer);
            UnitPriceDTO unitPriceDTO = EntityUtil.convertBean(item, UnitPriceDTO.class);

            try {
                OfferDTO personDTO = insuranceService.acciQuotation(offerReq);
                OfferDTO childrenDTO = insuranceService.acciQuotation(offerReq);
                offer.setPersonCount(0L);
                offer.setChildCount(1L);
                unitPriceDTO.setChildrenPrice(personDTO.getPremium());
                unitPriceDTO.setPersonPrice(childrenDTO.getPremium());
                unitPriceDTO.setUserInfo(userInfoDTO);
                return unitPriceDTO;
            } catch (Exception e) {
                log.error("第三方报价查询失败:" + e.getMessage());
                return unitPriceDTO;
            }
        }).collect(Collectors.toList());

        return Result.success(collect);
    }
}
